﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;

namespace ConsoleXmlParser
{
	public class CSVParser
	{
		private List<string> stories = new List<string>();
		private List<string> bugs = new List<string>();
		private List<string> features = new List<string>();

		internal void Parse(string filePathInputFile, string filePathSimplifiedXmlFile)
		{
			if (!File.Exists(filePathInputFile))
			{
				throw new FileNotFoundException(Constants.MESSAGE_FILE_DOESNT_EXIST);
			}

			using (StreamReader streamReader = new StreamReader(filePathInputFile))
			{
				streamReader.ReadLine();

				using (StreamWriter writer = new StreamWriter(filePathSimplifiedXmlFile))
				{
					writer.WriteLine(Constants.XML_FILE_HEADER);
					writer.WriteLine("<controls>");
					writer.WriteLine("<control>");

					string currentLine;
					string previousControlName = null;
					while ((currentLine = streamReader.ReadLine()) != null)
					{
						string[] columns = Regex.Split(currentLine, Constants.REGEX_COMMA_NOT_IN_QUOTES);
						string itemID = columns[0];
						string itemType = columns[1];
						string itemText = columns[2];
						string controlArea = columns[3];

						string plainControlArea = GetPlainControlArea(controlArea);
						if (previousControlName != plainControlArea)
						{
							this.WriteItems(writer);
							writer.WriteLine("</control>");
							previousControlName = plainControlArea;
							writer.WriteLine("<control>");
							writer.WriteLine("<area>" + plainControlArea + "</area>");
						}
						AddItem(itemType, itemText);
					}
					this.WriteItems(writer);
					writer.WriteLine("</control>");
					writer.WriteLine("</controls>");
				}
			}
		}

		private void AddItem(string itemType, string itemText)
		{
			if (itemType == Constants.BUG)
			{
				bugs.Add(itemText);
			}
			else
			{
				if (itemType == Constants.STORY)
				{
					stories.Add(itemText);
				}
				else
				{
					if (itemType == Constants.FEATURE)
					{
						features.Add(itemText);
					}
				}
			}
		}

		private void WriteItems(StreamWriter writer)
		{
			WriteFeatures(writer);
			WriteStories(writer);
			WriteBugs(writer);
		}

		private void WriteFeatures(StreamWriter writer)
		{
			WriteItemByType(writer, features,
				Constants.TAG_STORY_COLLECTION, Constants.TAG_STORY_COLLECTION_CLOSED, Constants.TAG_STORY, Constants.TAG_STORY_CLOSED);
		}

		private void WriteStories(StreamWriter writer)
		{
			WriteItemByType(writer, stories,
				Constants.TAG_STORY_COLLECTION, Constants.TAG_STORY_COLLECTION_CLOSED, Constants.TAG_STORY, Constants.TAG_STORY_CLOSED);
		}

		private void WriteBugs(StreamWriter writer)
		{
			WriteItemByType(writer, bugs,
				Constants.TAG_BUG_COLLECTION, Constants.TAG_BUG_COLLECTION_CLOSED, Constants.TAG_BUG, Constants.TAG_BUG_CLOSED);
		}

		private void WriteItemByType(StreamWriter writer, List<string> items, string openingCollectionTag, string closingCollectionTag, string openingItemTag, string closingItemTag)
		{
			if (items.Count > 0)
			{
				writer.WriteLine(openingCollectionTag);
				for (int i = 0; i < items.Count; i++)
				{
					string encodedItemText = HttpUtility.HtmlEncode(items[i]);
					string trimmedItemText = encodedItemText.Replace(Constants.QUOTE, Constants.EMPTY_STRING);
					writer.WriteLine(openingItemTag + trimmedItemText + closingItemTag);
				}
				writer.WriteLine(closingCollectionTag);
			}
			items.Clear();
		}

		private string GetPlainControlArea(string controlArea)
		{
			string[] areaSegments = controlArea.Split(Constants.BACKSLASH);
			string plainArea = "";
			if (areaSegments.Length > 1)
			{
				plainArea = areaSegments[1];
			}
			else
			{
				plainArea = controlArea;
			}
			plainArea = plainArea.Replace(Constants.RAD, Constants.EMPTY_STRING);
			plainArea = plainArea.Trim('"');

			return plainArea;
		}
	}
}
